 /*
 * QTXpost - a Qt-based blog client.
 * Copyright (C) 2010 Helen Sommer
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program (in COPYING); if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA  02111-1307  USA
 *
 * The project is hosted on http://code.google.com/p/qtxpost
 */

#include "MainWindow.h"
#include "Config.h"
#include "version.h"

extern Config *config;

MainWindow::MainWindow(QWidget *parent) 
  : QMainWindow(parent)
{
  setupUi(this);
  
  toolBar = new QToolBar(tr("Tools"));
  addToolBar(Qt::TopToolBarArea, toolBar);
  toolBar->setMovable(false);

  QAction *boldAction = new QAction(QString("B"), this);
  boldAction->setShortcut(tr("Ctrl+B"));
  boldAction->setToolTip(tr("Insert bold"));  
  QFont boldFont = boldAction->font();
  boldFont.setBold(true);
  boldFont.setFamily("Serif");
  boldAction->setFont(boldFont);
  toolBar->addAction(boldAction);
  connect(boldAction, SIGNAL(triggered()), this, SLOT(insertBold()));

  QAction *italicAction = new QAction(QString("I"), this);
  italicAction->setShortcut(tr("Ctrl+I"));
  italicAction->setToolTip(tr("Insert italic"));  
  QFont italicFont = italicAction->font();
  italicFont.setItalic(true);
  italicFont.setFamily("Serif");
  italicAction->setFont(italicFont);
  toolBar->addAction(italicAction);
  connect(italicAction, SIGNAL(triggered()), this, SLOT(insertItalic()));
  
  QAction *underlineAction = new QAction(QString("U"), this);
  underlineAction->setShortcut(tr("Ctrl+U"));
  underlineAction->setToolTip(tr("Insert underline"));  
  QFont underlineFont = underlineAction->font();
  underlineFont.setUnderline(true);
  underlineFont.setFamily("Serif");
  underlineAction->setFont(underlineFont);
  toolBar->addAction(underlineAction);
  connect(underlineAction, SIGNAL(triggered()), this, SLOT(insertUnderline()));
  
  QAction *overstrikeAction = new QAction(QString("abc"), this);
  overstrikeAction->setShortcut(tr("Ctrl+S"));
  overstrikeAction->setToolTip(tr("Insert overstrike"));  
  QFont overstrikeFont = overstrikeAction->font();
  overstrikeFont.setStrikeOut(true);
  overstrikeFont.setFamily("Serif");
  overstrikeAction->setFont(overstrikeFont);
  toolBar->addAction(overstrikeAction);
  connect(overstrikeAction, SIGNAL(triggered()), this, SLOT(insertOverstrike()));
  
  QAction *addressAction = new QAction(QIcon(":/images/link.png"), tr("Link"), this);
  addressAction->setToolTip(tr("Insert link"));
  QFont addressFont = addressAction->font();
  addressFont.setFamily("Serif");
  addressAction->setFont(addressFont);
  toolBar->addAction(addressAction);
  connect(addressAction, SIGNAL(triggered()), this, SLOT(insertAddress()));
  
  QAction *imageAction = new QAction(QIcon(":/images/image.png"), tr("Image"), this);
  imageAction->setToolTip(tr("Insert image"));  
  QFont imageFont = imageAction->font();
  imageFont.setFamily("Serif");
  imageAction->setFont(imageFont);
  toolBar->addAction(imageAction);
  connect(imageAction, SIGNAL(triggered()), this, SLOT(insertImage()));

  toolBar->addSeparator();

  QAction *cutAction = new QAction(QString("(---)"), this);
  cutAction->setToolTip(tr("Insert lj-cut")); 
  QFont cutFont = cutAction->font();
  cutFont.setFamily("Serif");
  cutAction->setFont(cutFont);
  toolBar->addAction(cutAction);
  connect(cutAction, SIGNAL(triggered()), this, SLOT(insertCut()));

  QAction *userAction = new QAction(QIcon(":/images/user.png"), tr("User"), this);
  userAction->setToolTip(tr("Insert lj user")); 
  toolBar->addAction(userAction);
  connect(userAction, SIGNAL(triggered()), this, SLOT(insertUser()));

  QAction *communityAction = new QAction(QIcon(":/images/community.png"), tr("Community"), this);
  communityAction->setToolTip(tr("Insert lj comm"));  
  toolBar->addAction(communityAction);
  connect(communityAction, SIGNAL(triggered()), this, SLOT(insertCommunity()));

  serverConfig = 0;
  postProgress = 0;
  preview = 0;
  selectPost = 0;
  friendsManager = 0;

  openFileDirectory = QDir::homePath();
  saveFileDirectory = QDir::homePath();

  securityCombo->addItem("public");
  securityCombo->addItem("friends");
  securityCombo->addItem("private");
  securityCombo->addItem("custom");

  moodsCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents);

  backdateLine->hide();
  hiddenLabel->hide();
  hiddenToggle->hide();
  lastpostLabel->hide();
  editpostToggle->hide();

  connect(actionQuit, SIGNAL(triggered()), this, SLOT(close()));
  connect(actionServers, SIGNAL(triggered()), this, SLOT(openServerConfig()));
  connect(actionPreferences, SIGNAL(triggered()), this, SLOT(openConfig()));
  connect(actionEditLastPost, SIGNAL(triggered()), this, SLOT(editLastPost()));
  connect(actionSelectPost, SIGNAL(triggered()), this, SLOT(selectEditPost()));
  connect(actionAbout, SIGNAL(triggered()), this, SLOT(about()));
  connect(actionOpenFile, SIGNAL(triggered()), this, SLOT(openFile()));
  connect(actionSaveFile, SIGNAL(triggered()), this, SLOT(saveFile()));
  connect(actionFriends, SIGNAL(triggered()), this, SLOT(openFriendsManager()));

  shortcutQuit = new QShortcut(QKeySequence(tr("Ctrl+Q", "Quit")), this, 0, 0, Qt::ApplicationShortcut);
  connect(shortcutQuit, SIGNAL(activated()), this, SLOT(close()));

  connect(config, SIGNAL(updated()), this, SLOT(updateProperties())); 
  connect(postButton, SIGNAL(clicked()), this, SLOT(post())); 
  connect(previewButton, SIGNAL(clicked()), this, SLOT(openPreview())); 
  connect(wordCountButton, SIGNAL(clicked()), this, SLOT(wordCount())); 
  connect(backdatedToggle, SIGNAL(stateChanged(int)), this, SLOT(toggleBackdated(int)));
  connect(detectMusicButton, SIGNAL(clicked()), this, SLOT(detectMusic()));

  serversLayout = new QHBoxLayout();
  serversLayout->setContentsMargins(4, 4, 4, 4);
  serversWidget->setLayout(serversLayout);
  selectedGroup = new QButtonGroup(this);
  selectedGroup->setExclusive(true);

  QSqlQuery query;
  query.exec("select count(*) as count from users");
  if (!query.next()) {
    qDebug() << "Error reading database! no data found for users table." ;
    exit(1);
  }

  int count = query.value(0).toInt();
  int width = 0;
  bool fixPosition = false;
  int position = -1;
  for (int i = 0; i < count; i++) {
    Server *server = new Server(i);
    servers.append(server);
    server->setMinimumWidth(120); 
    // can't setMinimumWidth in Qt Designer because it stops showing the contents of the frame
    // LJ icons are 100px, + some more width for keywords
    if (server->width() > width) 
      width = server->width();
    if (i > 0 && position == server->position) {
      fixPosition = true;
    }
    position = server->position;
  }

  if (fixPosition) {
    fixServersPosition();
  }

  for (int i = 0; i < servers.size(); i++) {
    servers.at(i)->setFixedWidth(width);
    serversLayout->addWidget(servers.at(i),1);
  }

  serversScrollArea->show();
  QScrollBar *scrollBar = serversScrollArea->horizontalScrollBar();
  /*
  if (scrollBar->isVisible()) { // FIX LATER - this does not work
    int height = scrollBar->height();
    printf("height=%d:%d\n", height, servers.at(0)->height());
    serversScrollArea->setFixedHeight(servers.at(0)->height() + height);
  }
  else {
    serversScrollArea->setFixedHeight(servers.at(0)->height());
  }
  */

  int height = scrollBar->height();
  if (servers.size()) {
    serversScrollArea->setFixedHeight(servers.at(0)->height() + height);
  }
  serversLayout->insertStretch(-1, 2);
  updateMoods();
  updateProperties();

  if (servers.size() == 0 ) {
    openServerConfig();
  }
}

void MainWindow::fixServersPosition()
// make sure that all "position" values are different and consecutive in db
{
  int position = 1;
  for (int i = 0; i < servers.size(); i++) {
    servers.at(i)->updatePosition(position++);
  }
}

void MainWindow::openServerConfig()
{
  if (serverConfig == 0) {
    serverConfig = new ServerConfig(this);
  }
  serverConfig->show();
}

void MainWindow::addServer(QString username, QString password, QString label, QString server_, int serverType)
{
  int width = 160; // no way to know what width it will need if it's the 1st
  if (servers.count()) {
    width = servers.at(0)->width();
  }

  Server *server = new Server(username, password, label, server_, serverType);
  servers.append(server);
  server->setFixedWidth(width); 

  //remove spacer (is there a way to add new widget just before spacer at the end?)
  for (int i = 0; i < serversLayout->count(); i++) {
    if (serversLayout->itemAt(i)->spacerItem()) {
      serversLayout->takeAt(i);
    }
  }
  serversLayout->addWidget(server, 1);
  serversLayout->insertStretch(-1, 2);
  if (servers.size() == 1) {
    QScrollBar *scrollBar = serversScrollArea->horizontalScrollBar();
    serversScrollArea->setFixedHeight(server->height() + scrollBar->height());
  }
}

static bool sortServers(const Server *s1, const Server *s2)
{
  return s1->position < s2->position;
}

void MainWindow::reorderServers()
{
  // delete all servers from the layout, then sort the list and add everything again
  // is it possible to reorder more efficiently ?

  QLayoutItem *child;
  while ((child = serversLayout->takeAt(0)) != 0) { }

  qSort(servers.begin(), servers.end(), sortServers);

  for (int i = 0; i < servers.size(); i++) {
    serversLayout->addWidget(servers.at(i), 1);
  }
  serversLayout->insertStretch(-1, 2);
}

void MainWindow::updateMoods()
{
  moods.clear();
  
  for (int i = 0; i < servers.size(); i++) {
    Server *server = servers.at(i);
    if (server->hidden || server->deleted) continue;
    for (int j = 0; j < server->moods.size(); j++) {
      moods[server->moods.at(j)].append(server->id);
    }
  }
  displayMoods();
}

void MainWindow::displayMoods()
{
  QList<int> displayed;

  for (int i = 0; i < servers.size(); i++) {
    Server *server = servers.at(i);
    if (server->hidden || server->deleted) continue;
    if (server->selected) 
      displayed.append(server->id);
  }   

  QString current = moodsCombo->currentText(); 
  QStringList moodsList;
  // insertAlphabetically() option of combobox doesn't work for some reason
  // so it's needed to sort manually

  moodsCombo->clear();
  moodsCombo->addItem("-----");
  QHashIterator<QString, QList <int> > j(moods);
  // make a list of moods merged from all selected servers
  while (j.hasNext()) {
    j.next();
    QString mood = j.key();
    QList<int> values = j.value();
    bool isOnce = false; // mood exists at least on one selected server
    bool isEverywhere = true; // mood exists on all selected servers

    for (int k = 0; k < displayed.size(); k++) {
      if (values.contains(displayed.at(k))) 
        isOnce = true;
      else 
        isEverywhere = false;
    }
    if (!isOnce) continue;

    //if mood doesn't exist on all servers, mark it with *
    if (!isEverywhere)
      mood.append('*');

    moodsList.append(mood);
  }

  moodsList.sort();
  moodsCombo->addItems(moodsList);
  moodsCombo->setCurrentIndex(moodsCombo->findText(current));
}

void MainWindow::updateIcons(int id, QString keyword)
{
  for (int i = 0; i < servers.size(); i++) {
    Server *server = servers.at(i);
    if (server->hidden || server->deleted) continue;
    if (id == server->id) continue;
    server->disableCopyIconKeyword();
    if (server->selected) server->setIconKeyword(keyword);
  }   
}

bool MainWindow::isValidBackdate()
{
  QMessageBox msgBox;
  QString error;
  bool ret = true;

  QString str = backdateLine->text().simplified();
  if (str == ""){
    error = QString(tr("Please enter date!"));
    ret = false;
  }
  else {
    QDateTime backdate = QDateTime::fromString(str, "yyyy-MM-dd HH:mm");
    if (!backdate.isValid()) {
      error = QString(tr("Invalid date!"));
      ret = false;
    }
  }
  if (!ret) {
    msgBox.setIcon(QMessageBox::Warning);
    msgBox.setText(error);
    msgBox.setInformativeText(tr("Format of date: yyyy-mm-dd hh:mm"));
    msgBox.exec();
  }
  return ret;
}

void MainWindow::post()
{
  QMessageBox msgBox;
  QString message;

  if (eventText->toPlainText().isEmpty()) {
    msgBox.setIcon(QMessageBox::Warning);
    msgBox.setText(tr("Post is empty!"));
    msgBox.exec();
    return;
  }

  if (backdatedToggle->isChecked()) {
    if (!isValidBackdate()) return;
  }

  if (postProgress == 0) {
    postProgress = new PostProgress(this);
  }

  isEdit = editpostToggle->isChecked();
  QString security = securityCombo->currentText();
  bool custom = (security == "custom");
  int count = 0;
  bool error = false;
  bool warning = false;

  for (int i = 0; i < servers.size(); i++) {
    Server *server = servers.at(i);
    if (server->hidden || server->deleted || !server->selected) continue;
    if (isEdit) {
      if (server->itemid <= 0) {
        message.append(QString(tr("%1: nothing selected to edit.\n")).arg(server->label));
        error = true;
      }
      else {
        // count++;
        // server->getCommunities(server->username); 
        count += server->getCommunities();
        if (!server->inSync) {
          message.append(QString(tr("%1: not in sync.\n")).arg(server->label));
          warning = true;
        }
      }
    }
    else {
      count += server->getCommunities();
      if (custom && !server->communities->groupMask) {
        message.append(QString(tr("Custom groups not selected: %1\n")).arg(server->label));
        error = true;
      }
    }
  }
  if (count == 0) {
    msgBox.setIcon(QMessageBox::Warning);
    msgBox.setText(tr("No servers are selected to post!"));
    msgBox.exec();
    return;
  }
  if (error) {
    msgBox.setIcon(QMessageBox::Warning);
    msgBox.setText(message);
    msgBox.exec();
    return;
  }
  if (warning) { // not in sync but no errors - can proceed to update if user selects "force"
    msgBox.setIcon(QMessageBox::Warning);
    msgBox.setText(message);
    msgBox.setInformativeText(tr("Do you want to force the update anyway?"));
    msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
    msgBox.setDefaultButton(QMessageBox::No);
    int ret = msgBox.exec();
    if (ret != QMessageBox::Yes) return;
  }

  postProgress->initialize(count, true);
  postProgress->show();

  for (int i = 0; i < servers.size(); i++) {
    Server *server = servers.at(i);
    if (server->hidden || server->deleted || !server->selected) continue;
    server->startPost();
  }
}

void MainWindow::editLastPost()
{
  if (postProgress == 0) {
    postProgress = new PostProgress();
  }

  int count = 0;
  for (int i = 0; i < servers.size(); i++) {
    Server *server = servers.at(i);
    if (server->hidden || server->deleted || !server->selected) continue;
    count++;
  }

  if (!count) {
    QMessageBox msgBox;
    msgBox.setIcon(QMessageBox::Warning);
    msgBox.setText(tr("Please select a server to get the last post."));
    msgBox.exec();
    return;
  }

  postProgress->initialize(count, true);
  postProgress->show();
  //  connect(postProgress, SIGNAL(finished()), this, SLOT(validateLastPost()));

  // getting the post contents only from the 1st selected server
  // from the others - only itemid and properties (icon, date, custom groups etc)
  editedServer = -1; 
  isLastPost = true;
  for (int i = 0; i < servers.size(); i++) {
    Server *server = servers.at(i);
    if (server->hidden || server->deleted || !server->selected) continue;
    server->getCommunities();
    server->startGetLastPost();
    editedServer = i;
    break;
  }
}

void MainWindow::findItems()
{
  int count = 0;
  for (int i = 0; i < servers.size(); i++) {
    if (i == editedServer) continue;
    Server *server = servers.at(i);
    if (server->hidden || server->deleted || !server->selected) continue;
    count++;
  }

  if (!count) { // no other accounts are selected - only one is being edited
    return;
  }

  //  postProgress->initialize(count, false);
  //  postProgress->show();
  if (isLastPost) {
    connect(postProgress, SIGNAL(finished()), this, SLOT(validateLastPost()));
  }

  lastSubject = servers.at(editedServer)->lastSubject;
  lastDate = servers.at(editedServer)->lastDate;
  // find entries which may correspond to the currently edited post
  for (int i = 0; i < servers.size(); i++) {
    if (i == editedServer) continue;
    Server *server = servers.at(i);
    if (server->hidden || server->deleted || !server->selected) continue;
    server->getCommunities();
    if (isLastPost) {
      server->startGetLastItem();
    }
    else {
      server->startFindItem();
    }
  }
}

void MainWindow::editPost(Server *server_)
{
  if (postProgress == 0) {
    postProgress = new PostProgress();
  }

  int count = 1; //TEMP
  postProgress->initialize(count, true);
  postProgress->show();

  editedServer = -1; 
  for (int i = 0; i < servers.size(); i++) {
    Server *server = servers.at(i);
    if (server->hidden || server->deleted || !server->selected) continue;
    if (server == server_) {
      server->getCommunities();
      server->startGetPost();
      editedServer = i;
    }
    else {
      server->itemid = -1;
      server->inSync = false;
    }
  }
}

void MainWindow::validateLastPost()
{
  // check (approx.) if last posts from all selected servers are in sync
  // if not, display the warning (but do not cancel editing)

  if (servers.size() > 0 && editedServer != -1) { // check just in case

    QString subject = servers.at(editedServer)->lastSubject;
    QDateTime date = servers.at(editedServer)->lastDate;
    //  QDateTime date = QDateTime::fromString(backdateLine->text().simplified(), "yyyy-MM-dd HH:mm");
    
    for (int i = 0; i < servers.size(); i++) {
      if (i == editedServer) continue;
      Server *server = servers.at(i);
      if (server->hidden || server->deleted || !server->selected) continue;
      
      QString errorMessage; // error message is set in eventInSync
      if (!server->eventInSync(subject, date, errorMessage)) {
        postProgress->update(QString(tr("Warning: last post at %1 is not in sync. %2")).arg(server->label).arg(errorMessage));
      }
    }
  }
  disconnect(postProgress, SIGNAL(finished()), this, SLOT(validateLastPost()));
}

void MainWindow::toggleBackdated(int)
{
  if (backdatedToggle->isChecked()) {
    backdateLine->show();
    hiddenLabel->show();
    hiddenToggle->show();
  }
  else {
    backdateLine->hide();
    hiddenLabel->hide();
    hiddenToggle->hide();
  }
}

void MainWindow::openPreview()
{
  if (preview == 0) {
    preview = new Preview(this);
  }

  QString start = QString("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" /></head><body>");
  QString end = QString("</body></html>");
  QString event = eventText->toPlainText();
  event.replace("\n","<br/>");

  // replace LJ user and comm tags with corresponding icons
  QString userinfo = QString("<img src=\"qrc:/images/user.png\">");
  QString community = QString("<img src=\"qrc:/images/community.png\">");
  QRegExp ljuser("(<lj user=\"|<user=\")(\\w+)(\">|\"\\/>)");
  QRegExp ljcomm("(<lj comm=\"|<comm=\")(\\w+)(\">|\"\\/>)");
  event.replace(ljuser,userinfo.append("<b>\\2</b>"));
  event.replace(ljcomm,community.append("<b>\\2</b>"));

  preview->setText(event);
  preview->show();
}

void MainWindow::openConfig()
{
  config->show();
}

void MainWindow::about()
{
  QString message = QString(tr("QTXpost version %1\nCopyright (C) 2010, Helen Sommer")).arg(VERSION);
  QMessageBox::about(this,"About QTXpost",message);
}

void MainWindow::updateProperties()
{
  if (config->settings.value("show_toolbar").toBool()) {
    toolBar->show();
  }
  else {
    toolBar->hide();
  }
  if (config->settings.value("show_music").toBool()) {
    musicLine->show();
    musicLabel->show();
    detectMusicButton->show();
  }
  else {
    musicLine->hide();
    musicLabel->hide();
    detectMusicButton->hide();
  }

  if (config->settings.value("show_tags").toBool()) {
    tagsLine->show();
    tagsLabel->show();
  }
  else { 
    tagsLine->hide();
    tagsLabel->hide();
  }

  if (config->settings.value("show_location").toBool()) {
    locationLine->show();
    locationLabel->show();
  }
  else {
    locationLine->hide();
    locationLabel->hide();
  }

  if (config->settings.value("show_wordcount").toBool()) {
    wordCountButton->show();
    wordCountField->show();
  }
  else {
    wordCountButton->hide();
    wordCountField->hide();
  }

  if (config->settings.value("crossposting").toBool()) { 
    // with xposting, one can select multiple servers
    // so we remove checkboxes from the exclusive buttongroup
    // simply setting the buttongroup type to non-exclusive doesn't work for some reason

    QList<QAbstractButton *> buttonsList = selectedGroup->buttons();
    for (int i = 0; i < buttonsList.size(); i++) {
      selectedGroup->removeButton(buttonsList.at(i));
    }
  }
  else {
    for (int i = 0; i < servers.size(); i++) {
      QCheckBox *checkBox = servers.at(i)->getSelected();
      selectedGroup->addButton(checkBox);
    }
  }

  securityCombo->setCurrentIndex(securityCombo->findText(config->settings.value("security").toString()));

  if (config->settings.value("shortcut_quit").toBool()) {
    shortcutQuit->setEnabled(true);
  }
  else {
    shortcutQuit->setEnabled(false);
  }
}

void MainWindow::setLastPost(QString url, QString subject, QString eventtime, 
                             QString security, qlonglong allowmask, QString event,
                             QString current_mood, QString taglist,
                             QString current_music, QString current_location)
{
  lastpostLabel->setText(url);
  lastpostLabel->show();
  editpostToggle->show();
  editpostToggle->setChecked(true);
  subjectLine->setText(subject);
  eventtime.replace(QRegExp(":\\d\\d$"),"");
  backdateLine->setText(eventtime);
  backdateLine->show();
  hiddenToggle->show();
  backdatedToggle->setChecked(true);
  tagsLine->setText(taglist);
  musicLine->setText(current_music);
  locationLine->setText(current_location);

  if (security == "") {
    security = "public";
  }
  else if (security == "usemask") {
    if (allowmask == 1) {
      security = "friends";
    }
    else {
      security = "custom";
    }
  }
  securityCombo->setCurrentIndex(securityCombo->findText(security));

  if (current_mood != "") {
    current_mood.replace("*", "");
    bool found = false;
    for (int i = 0; i < moodsCombo->count(); i++) {
      if (moodsCombo->itemText(i).replace("*","") == current_mood) {
        moodsCombo->setCurrentIndex(i);
        found = true;
        break;
      }
    }
    if (!found) {
      moodsCombo->setCurrentIndex(0);
      moodLine->setText(current_mood);
    }
  }
  else {
    moodsCombo->setCurrentIndex(0);
    moodLine->clear();    
  }

  event.replace("\r\n","\n");
  QString signature = config->settings.value("signature").toString();
  if (signature != "") {
    event.replace(signature,"");
  }
  eventText->setPlainText(event);

  findItems();
}

void MainWindow::wordCount()
// uses UNIX 'wc', to ensure compatibility with NaNoWriMo word counter
{
  QString txt = eventText->toPlainText();
  QProcess wc;
  wc.start("wc", QStringList() << "-w");
  if (!wc.waitForStarted()) return;
  wc.write(txt.toAscii().data());
  wc.closeWriteChannel();
  if (!wc.waitForFinished()) return;

  QByteArray result = wc.readAll();
  QString str(result);
  wordCountField->setText(str);
}

QString MainWindow::getMood()
{
  QString mood = moodLine->text().simplified();
  if (mood == "") {
    mood = moodsCombo->currentText().replace("*","");
    if (mood == "-----") 
      mood = "";
  }
  return mood.toUtf8();
}

QString MainWindow::getDate()
{
  if (backdatedToggle->isChecked()) {
    return backdateLine->text().simplified();
  }
  else {
    return "";
  }
}

QString MainWindow::getSubject()
{
  return subjectLine->text().toUtf8();
}

QString MainWindow::getSecurity()
{
  return securityCombo->currentText();
}

QString MainWindow::getMusic()
{
  return (musicLine->isHidden()) ? "" : musicLine->text().simplified().toUtf8();
}

QString MainWindow::getLocation()
{
  return (locationLine->isHidden()) ? "" : locationLine->text().simplified().toUtf8();
}

QString MainWindow::getTags()
{
  return (tagsLine->isHidden()) ? "" : tagsLine->text().simplified().split(",",QString::SkipEmptyParts).join(",").toUtf8();
}

QByteArray MainWindow::getText()
{
  QByteArray event = eventText->toPlainText().toUtf8();

  if (config->settings.value("add_signature").toBool()) {
    event.append(config->settings.value("signature").toString());
  }
  return event;
}

bool MainWindow::isHidden()
{
  return (hiddenToggle->isChecked());
}


void MainWindow::selectEditPost()
{

  if (selectPost == 0) {
    selectPost = new SelectPost(this);
  }
  selectPost->raise();
  
  int count = 0;
  for (int i = 0; i < servers.size(); i++) {
    Server *server = servers.at(i);
    if (server->hidden || server->deleted || !server->selected) continue;
    count++;
  }

  if (!count) {
    QMessageBox msgBox;
    msgBox.setIcon(QMessageBox::Warning);
    msgBox.setText(tr("Please select a server to get the list of posts."));
    msgBox.exec();
    return;
  }

  isLastPost = false;
  // getting the list from the 1st selected server
  for (int i = 0; i < servers.size(); i++) {
    Server *server = servers.at(i);
    if (server->hidden || server->deleted || !server->selected) continue;
    selectPost->initialize(server);
    server->getCommunities();
    server->startGetListPosts();
    break;
  }
}

void MainWindow::openFile()
{
  QMessageBox msgBox;
  msgBox.setIcon(QMessageBox::Warning);

  QFileDialog dialog; 
  //  connect (&dialog, SIGNAL(directoryEntered(QString)), this, SLOT(openFileDirectoryEntered(QString))); // doesn't work
  
  QString fileName = dialog.getOpenFileName(this, tr("Open file"), 
                                            openFileDirectory,
                                             tr("All files (*);;Text files (*.txt)"));

  if (fileName == "") return;
  openFileDirectory = fileName;
  openFileDirectory.truncate(openFileDirectory.lastIndexOf("/"));

  QFile file(fileName);
  if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
    msgBox.setText(QString(tr("Can't open file %1.")).arg(fileName));
    msgBox.exec();
    return;
  }
  
  if (file.size() > 65535) { // LJ post limit 
    msgBox.setText(QString(tr("File %1 exceeds the size limit (64K)")).arg(fileName));
    msgBox.exec();
    return;
  }
  
  QString contents;
  QTextStream in(&file);
  while (!in.atEnd()) {
    contents.append(in.readLine());
    contents.append("\n");
  }
  file.close();
  eventText->setPlainText(contents);
}

void MainWindow::saveFile()
{
  QMessageBox msgBox;
  msgBox.setIcon(QMessageBox::Warning);

  QFileDialog dialog; 
  //  connect (&dialog, SIGNAL(directoryEntered(QString)), this, SLOT(saveFileDirectoryEntered(QString))); // doesn't work

  QString fileName = dialog.getSaveFileName(this, tr("Save file"),
                                            saveFileDirectory,
                                            tr("All files (*);;Text files (*.txt)"));
  if (fileName == "") return;
  saveFileDirectory = fileName;
  saveFileDirectory.truncate(saveFileDirectory.lastIndexOf("/"));
  QFile file(fileName);
  // existence of the file is checked by default
  if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
    msgBox.setText(QString(tr("Can't open file %1 for writing.")).arg(fileName));
    msgBox.exec();
    return;
  }
  
  QTextStream out(&file);
  out << eventText->toPlainText();
  file.close();

}

void MainWindow::detectMusic()
// currently only amarok
{
  QProcess detect;
  
  detect.start("dcop", QStringList() << "amarok" << "player" << "nowPlaying");
  if (!detect.waitForStarted())
    return;

  if (!detect.waitForFinished())
    return;

  QByteArray result = detect.readAll();
  QString music = QString(result).simplified();
  musicLine->setText(music);
}

void MainWindow::insertBold()
{
  eventText->insertPlainText(QString( "<strong>%1</strong>" )
                             .arg( eventText->textCursor().selectedText() ) );
}

void MainWindow::insertItalic()
{
  eventText->insertPlainText(QString( "<em>%1</em>" )
                             .arg( eventText->textCursor().selectedText() ) );
}

void MainWindow::insertUnderline()
{
  eventText->insertPlainText(QString("<u>%1</u>")
                             .arg( eventText->textCursor().selectedText() ) );
}

void MainWindow::insertOverstrike()
{
  eventText->insertPlainText(QString( "<strike>%1</strike>" )
                             .arg( eventText->textCursor().selectedText() ) );
}

void MainWindow::insertAddress()
{
  eventText->insertPlainText("<a href=\"\"></a>");
}

void MainWindow::insertImage()
{
  QString insertionString;
  QDialog image_entry( this );
  Ui::ImageEntry ieui;
#ifdef Q_WS_MAC
  image_entry.setWindowFlags( Qt::Sheet );
#endif
  ieui.setupUi( &image_entry );
  if( image_entry.exec() ) {
    insertionString = QString( "<img src=\"%1\"" )
      .arg( ieui.leImageURL->text() );
    if( ieui.leTitle->text().size() )
      insertionString += QString( " title=\"%1\"" )
        .arg( ieui.leTitle->text() );
    if( ieui.leAltText->text().size() )
      insertionString += QString( " alt=\"%1\"" )
        .arg( ieui.leAltText->text() );
    if( ieui.chAlign->isChecked() ) {
      if( ieui.cbAlign->currentIndex() )
        insertionString += " align=\"right\"";
      else
        insertionString += " align=\"left\"";
    }
    insertionString += " />";
    eventText->insertPlainText( insertionString );
  }
}

void MainWindow::insertCut()
{
  eventText->insertPlainText("<cut text=\"\">\n</cut>");
}

void MainWindow::insertUser()
{
  eventText->insertPlainText("<user=\"\">");
}

void MainWindow::insertCommunity()
{
  eventText->insertPlainText("<comm=\"\">");
}

void MainWindow::openFriendsManager()
{
  if (friendsManager == 0) {
    friendsManager = new FriendsManager(this);
  }
  friendsManager->open();
}

